package com.yanqu.road.api.test;

import com.google.protobuf.GeneratedMessage;
import com.google.protobuf.InvalidProtocolBufferException;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.pb.bag.BagProto;
import com.yanqu.road.pb.player.AttributeProto;
import com.yanqu.road.pb.player.PlayerProto;
import com.yanqu.road.server.protocol.ClientProtocol;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * wmm
 * 2023/2/5
 */
public class JobManager {

    private static final Logger logger = LogManager.getLogger(JobManager.class.getName());

    //jobId, job
    private static Map<Long, TestJob> jobMap = new ConcurrentHashMap<>();

    //userId, jobId
    private static Map<Long, Long> userJobMap = new ConcurrentHashMap<>();

    //jobId, message
    private static Map<Long, List<String>> messageMap = new ConcurrentHashMap<>();

    private static AtomicLong jobId = new AtomicLong(0);

    private static Map<Long, List<YanQuMessage>> jobMessageMap = new ConcurrentHashMap<>();

    private static List<Integer> ignoreCodeList = new ArrayList<>();

    private static final Map<Integer, GeneratedMessage> syncCodeMessageMap = new HashMap<>();

    public static TestJob newJob(long userId){
        if(userJobMap.containsKey(userId)){
            return jobMap.get(userJobMap.get(userId));
        }
        TestJob job = new TestJob(jobId.incrementAndGet(), userId);
        jobMap.put(job.getJobId(), job);
        userJobMap.put(userId, job.getJobId());
        logger.info("new Job " + userId);
        startJob(job.getJobId());
        return job;
    }

    public static int startJob(long jobId){
        if(!jobMap.containsKey(jobId)){
            return -1;
        }
        jobMap.get(jobId).start();
        return 0;
    }

    public static int stopJob(long jobId){
        if(!jobMap.containsKey(jobId)){
            return -1;
        }
        jobMap.get(jobId).stop();
        return 0;
    }

    public static int pauseJob(long jobId){
        if(!jobMap.containsKey(jobId)){
            return -1;
        }
        jobMap.get(jobId).pause();
        return 0;
    }

    public static TestJob getJobById(long jobId){
        return jobMap.get(jobId);
    }

    public static Map<Long, TestJob> getJobMap() {
        return jobMap;
    }

    public static TestJob removeJob(long jobId){
        TestJob job = jobMap.remove(jobId);
        if(job != null){
            userJobMap.remove(job.getUserId());
            jobMessageMap.remove(jobId);
        }
        return job;
    }

    public static TestJob getJobByUserId(long userId){
        if(userJobMap.containsKey(userId)){
            return getJobById(userJobMap.get(userId));
        }
        return null;
    }

    public static void addResponse(long jobId, YanQuMessage message) {
        if(ignoreCodeList.contains(message.getCode())){
            return;
        }
        if(!messageMap.containsKey(jobId)){
            synchronized (messageMap){
                if(!messageMap.containsKey(jobId)){
                    messageMap.put(jobId, new ArrayList<>());
                }
            }
        }
        List<String> list = messageMap.get(jobId);
        if(list != null){
            synchronized (list){
                TestJob job = getJobById(jobId);
                if(job != null){
                    com.google.protobuf.Message.Builder builder = TestJob.parseFrom(message.getBytes(), message.getCode() + 20000);
                    if(builder != null) {
                        String result = job.parseRespToJSON(builder, message.getCode());
                        list.add(result);
                    }else {
                        if(syncCodeMessageMap.containsKey(message.getCode())){
                            GeneratedMessage gm = syncCodeMessageMap.get(message.getCode());
                            try {
                                builder = gm.toBuilder().mergeFrom(message.getBytes());
                                String result = job.parseRespToJSON(builder, message.getCode());
                                list.add(result);
                            } catch (InvalidProtocolBufferException e) {
                                e.printStackTrace();
                            }
                            return;
                        }
                        StringBuilder str = new StringBuilder();
                        str.append("{userId:").append(message.getPlayerId()).append(",code:").append(message.getCode()).append("}");
                        list.add(str.toString());
                    }
                }
            }
        }
    }

    public static Map<Long, List<String>> getMessageMap() {
        return messageMap;
    }

    public static Map<Long, List<YanQuMessage>> getJobMessageMap() {
        return jobMessageMap;
    }

    public static void addJobRunningMessage(long jobId, YanQuMessage msg){
        if(!jobMessageMap.containsKey(jobId)){
            jobMessageMap.put(jobId, new ArrayList<>());
        }
        jobMessageMap.get(jobId).add(msg);
    }

    static {
        //背包
        syncCodeMessageMap.put(ClientProtocol.U_BAG_SYNC_DATA, BagProto.BagRespMsg.getDefaultInstance());
        //玩家属性
        syncCodeMessageMap.put(ClientProtocol.U_ATTRIBUTE_SYNC, AttributeProto.AttributeListMsg.getDefaultInstance());
        //赚速
        syncCodeMessageMap.put(ClientProtocol.U_EARN_SPEED_SYNC, PlayerProto.EarnSpeedTempMsg.getDefaultInstance());
    }
}
